<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>学生成绩管理系统</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
  <script src="https://cdn.jsdelivr.net/npm/vue@3.3.4/dist/vue.global.prod.js"></script>
  <script>
    tailwind.config = {
      theme: {
        extend: {
          colors: {
            primary: '#3b82f6',
            secondary: '#64748b',
            success: '#10b981',
            danger: '#ef4444',
            warning: '#f59e0b',
            info: '#06b6d4',
            light: '#f8fafc',
            dark: '#1e293b'
          },
          fontFamily: {
            inter: ['Inter', 'system-ui', 'sans-serif'],
          },
        },
      }
    }
  </script>
  <style type="text/tailwindcss">
    @layer utilities {
      .content-auto {
        content-visibility: auto;
      }
      .table-shadow {
        box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
      }
      .hover-lift {
        transition: transform 0.2s ease, box-shadow 0.2s ease;
      }
      .hover-lift:hover {
        transform: translateY(-2px);
        box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
      }
      .slide-in {
        animation: slideIn 0.3s ease forwards;
      }
      .fade-in {
        animation: fadeIn 0.3s ease forwards;
      }
      @keyframes slideIn {
        from { transform: translateY(20px); opacity: 0; }
        to { transform: translateY(0); opacity: 1; }
      }
      @keyframes fadeIn {
        from { opacity: 0; }
        to { opacity: 1; }
      }
      .score-bar {
        transition: width 0.5s ease-in-out;
      }
    }
  </style>
</head>
<body class="bg-gray-50 font-inter min-h-screen">
  <div id="app">
    <!-- 顶部导航栏 -->
    <header class="bg-primary text-white shadow-md sticky top-0 z-40">
      <div class="container mx-auto px-4 py-4 flex justify-between items-center">
        <h1 class="text-2xl font-bold flex items-center">
          <i class="fa fa-graduation-cap mr-2"></i>
          学生成绩管理系统
        </h1>
        <div class="flex items-center space-x-4">
          <button
            @click="openAddStudentModal"
            class="bg-white text-primary hover:bg-gray-100 transition-colors px-4 py-2 rounded-md font-medium shadow-sm flex items-center"
          >
            <i class="fa fa-plus mr-2"></i>添加学生
          </button>
          <div class="relative">
            <span class="absolute -top-2 -right-2 bg-danger text-white text-xs rounded-full w-5 h-5 flex items-center justify-center">
              {{ students.length }}
            </span>
            <button class="text-white hover:text-gray-200 transition-colors">
              <i class="fa fa-bell text-xl"></i>
            </button>
          </div>
        </div>
      </div>
    </header>

    <!-- 主内容区 -->
    <main class="container mx-auto px-4 py-8">
      <!-- 统计卡片 -->
      <div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
        <div class="bg-white rounded-lg p-6 shadow-md hover-lift slide-in" style="animation-delay: 0.1s">
          <div class="flex items-center justify-between">
            <div>
              <p class="text-gray-500 text-sm">学生总数</p>
              <h3 class="text-2xl font-bold mt-1">{{ students.length }}</h3>
            </div>
            <div class="w-12 h-12 rounded-full bg-blue-100 flex items-center justify-center text-primary">
              <i class="fa fa-users text-xl"></i>
            </div>
          </div>
          <div class="mt-4 flex items-center text-sm">
            <span class="text-success flex items-center">
              <i class="fa fa-arrow-up mr-1"></i> 2 名新学生
            </span>
            <span class="text-gray-400 ml-3">本月</span>
          </div>
        </div>

        <div class="bg-white rounded-lg p-6 shadow-md hover-lift slide-in" style="animation-delay: 0.2s">
          <div class="flex items-center justify-between">
            <div>
              <p class="text-gray-500 text-sm">平均分</p>
              <h3 class="text-2xl font-bold mt-1">
                {{ (students.reduce((sum, student) => sum + student.average, 0) / students.length).toFixed(1) || 0 }}
              </h3>
            </div>
            <div class="w-12 h-12 rounded-full bg-green-100 flex items-center justify-center text-success">
              <i class="fa fa-line-chart text-xl"></i>
            </div>
          </div>
          <div class="mt-4 flex items-center text-sm">
            <span class="text-success flex items-center">
              <i class="fa fa-arrow-up mr-1"></i> 3.2%
            </span>
            <span class="text-gray-400 ml-3">较上月</span>
          </div>
        </div>

        <div class="bg-white rounded-lg p-6 shadow-md hover-lift slide-in" style="animation-delay: 0.3s">
          <div class="flex items-center justify-between">
            <div>
              <p class="text-gray-500 text-sm">优秀率</p>
              <h3 class="text-2xl font-bold mt-1">
                {{ ((students.filter(student => student.average >= 85).length / students.length) * 100).toFixed(1) || 0 }}%
              </h3>
            </div>
            <div class="w-12 h-12 rounded-full bg-purple-100 flex items-center justify-center text-purple-600">
              <i class="fa fa-trophy text-xl"></i>
            </div>
          </div>
          <div class="mt-4 flex items-center text-sm">
            <span class="text-danger flex items-center">
              <i class="fa fa-arrow-down mr-1"></i> 1.5%
            </span>
            <span class="text-gray-400 ml-3">较上月</span>
          </div>
        </div>
      </div>

      <!-- 搜索和筛选 -->
      <div class="mb-6 bg-white p-4 rounded-lg shadow-md">
        <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
          <div class="relative w-full md:w-64">
            <input
              type="text"
              v-model="searchQuery"
              placeholder="搜索学生姓名..."
              class="w-full pl-10 pr-4 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none transition-all"
            >
            <i class="fa fa-search absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400"></i>
          </div>

          <div class="flex flex-wrap gap-2">
            <button
              @click="sortBy('name')"
              class="px-4 py-2 bg-primary/10 hover:bg-primary/20 text-primary rounded-md transition-colors flex items-center"
            >
              姓名
              <i class="fa fa-sort ml-1"></i>
            </button>
            <button
              @click="sortBy('math')"
              class="px-4 py-2 bg-primary/10 hover:bg-primary/20 text-primary rounded-md transition-colors flex items-center"
            >
              数学
              <i class="fa fa-sort ml-1"></i>
            </button>
            <button
              @click="sortBy('english')"
              class="px-4 py-2 bg-primary/10 hover:bg-primary/20 text-primary rounded-md transition-colors flex items-center"
            >
              英语
              <i class="fa fa-sort ml-1"></i>
            </button>
            <button
              @click="sortBy('average')"
              class="px-4 py-2 bg-primary/10 hover:bg-primary/20 text-primary rounded-md transition-colors flex items-center"
            >
              平均分
              <i class="fa fa-sort ml-1"></i>
            </button>

            <div class="relative">
              <select
                v-model="filterGrade"
                class="appearance-none bg-white border border-gray-300 text-gray-700 py-2 px-4 pr-8 rounded-lg leading-tight focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary"
              >
                <option value="">全部成绩</option>
                <option value="excellent">优秀 (85+)</option>
                <option value="good">良好 (70-84)</option>
                <option value="average">中等 (60-69)</option>
                <option value="poor">不及格 (&lt;60)</option>
              </select>
              <div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
                <i class="fa fa-chevron-down text-xs"></i>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 学生成绩表格 -->
      <div class="bg-white rounded-lg overflow-hidden table-shadow">
        <div class="overflow-x-auto">
          <table class="w-full">
            <thead>
              <tr class="bg-gray-50 border-b">
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">ID</th>
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">姓名</th>
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">数学</th>
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">英语</th>
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">平均分</th>
                <th class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">排名</th>
                <th class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">操作</th>
              </tr>
            </thead>
            <tbody class="divide-y divide-gray-200">
              <template v-for="(student, index) in filteredStudents" :key="student.id">
                <tr
                  class="hover:bg-gray-50 transition-colors cursor-pointer hover-lift"
                  @click="showStudentDetail(student)"
                >
                  <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
                    {{ student.id }}
                  </td>
                  <td class="px-6 py-4 whitespace-nowrap text-sm font-medium text-primary">
                    {{ student.name }}
                  </td>
                  <td class="px-6 py-4 whitespace-nowrap text-sm">
                    <span
                      :class="{
                        'text-success': student.math >= 85,
                        'text-warning': student.math >= 70 && student.math < 85,
                        'text-primary': student.math >= 60 && student.math < 70,
                        'text-danger': student.math < 60
                      }"
                    >
                      {{ student.math }}
                    </span>
                  </td>
                  <td class="px-6 py-4 whitespace-nowrap text-sm">
                    <span
                      :class="{
                        'text-success': student.english >= 85,
                        'text-warning': student.english >= 70 && student.english < 85,
                        'text-primary': student.english >= 60 && student.english < 70,
                        'text-danger': student.english < 60
                      }"
                    >
                      {{ student.english }}
                    </span>
                  </td>
                  <td class="px-6 py-4 whitespace-nowrap text-sm">
                    <span
                      :class="{
                        'text-success': student.average >= 85,
                        'text-warning': student.average >= 70 && student.average < 85,
                        'text-primary': student.average >= 60 && student.average < 70,
                        'text-danger': student.average < 60
                      }"
                    >
                      {{ student.average.toFixed(1) }}
                    </span>
                  </td>
                  <td class="px-6 py-4 whitespace-nowrap text-sm">
                    <span class="inline-flex items-center justify-center w-6 h-6 rounded-full bg-gray-100 text-gray-800 text-xs font-medium">
                      {{ index + 1 + (currentPage - 1) * pageSize }}
                    </span>
                  </td>
                  <td class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
                    <button
                      @click="deleteStudent(student.id, $event)"
                      class="text-danger hover:text-danger/80 transition-colors mr-3"
                      title="删除学生"
                    >
                      <i class="fa fa-trash"></i>
                    </button>
                    <button
                      @click="editStudent(student, $event)"
                      class="text-primary hover:text-primary/80 transition-colors"
                      title="编辑学生"
                    >
                      <i class="fa fa-pencil"></i>
                    </button>
                  </td>
                </tr>
              </template>
            </tbody>
          </table>
        </div>

        <!-- 空状态 -->
        <div v-if="filteredStudents.length === 0" class="py-12 text-center">
          <i class="fa fa-search text-gray-300 text-4xl mb-4"></i>
          <p class="text-gray-500">没有找到匹配的学生记录</p>
          <button
            @click="resetFilters"
            class="mt-4 px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors"
          >
            重置筛选条件
          </button>
        </div>
      </div>

      <!-- 分页 -->
      <div class="mt-6 flex justify-between items-center">
        <div class="text-sm text-gray-500">
          显示 {{ (currentPage - 1) * pageSize + 1 }} 到 {{ Math.min(currentPage * pageSize, filteredStudents.length) }} 条，共 {{ filteredStudents.length }} 条记录
        </div>
        <div class="flex space-x-2">
          <button
            @click="prevPage"
            :disabled="currentPage === 1"
            class="px-3 py-1 rounded border border-gray-300 bg-white text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
          >
            上一页
          </button>
          <div class="flex">
            <button
              v-for="page in Math.ceil(filteredStudents.length / pageSize)"
              :key="page"
              :class="{
                'bg-primary text-white': currentPage === page,
                'bg-white text-gray-700 hover:bg-gray-50': currentPage !== page
              }"
              @click="currentPage = page"
              class="px-3 py-1 rounded border border-gray-300 mx-1 transition-colors"
            >
              {{ page }}
            </button>
          </div>
          <button
            @click="nextPage"
            :disabled="currentPage * pageSize >= filteredStudents.length"
            class="px-3 py-1 rounded border border-gray-300 bg-white text-gray-700 hover:bg-gray-50 disabled:opacity-50 disabled:cursor-not-allowed transition-colors"
          >
            下一页
          </button>
        </div>
      </div>
    </main>

    <!-- 添加/编辑学生模态框 -->
    <div v-if="studentModalOpen" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 fade-in">
      <div class="bg-white rounded-lg shadow-xl w-full max-w-md mx-4 overflow-hidden transform transition-all slide-in">
        <div class="bg-primary text-white p-4 flex justify-between items-center">
          <h2 class="text-xl font-bold">
            {{ isEditMode ? '编辑学生' : '添加学生' }}
          </h2>
          <button @click="closeStudentModal" class="text-white hover:text-gray-200">
            <i class="fa fa-times"></i>
          </button>
        </div>
        <div class="p-6">
          <form @submit.prevent="saveStudent">
            <div class="mb-4">
              <label for="name" class="block text-sm font-medium text-gray-700 mb-1">姓名</label>
              <input
                type="text"
                id="name"
                v-model="studentForm.name"
                class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none transition-all"
                :class="{ 'border-danger': formErrors.name }"
              >
              <p v-if="formErrors.name" class="text-danger text-xs mt-1">{{ formErrors.name }}</p>
            </div>

            <div class="grid grid-cols-2 gap-4 mb-6">
              <div>
                <label for="math" class="block text-sm font-medium text-gray-700 mb-1">数学成绩</label>
                <div class="relative">
                  <input
                    type="number"
                    id="math"
                    v-model.number="studentForm.math"
                    class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none transition-all"
                    min="0"
                    max="100"
                    :class="{ 'border-danger': formErrors.math }"
                  >
                  <div class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 text-sm">
                    /100
                  </div>
                </div>
                <p v-if="formErrors.math" class="text-danger text-xs mt-1">{{ formErrors.math }}</p>
              </div>

              <div>
                <label for="english" class="block text-sm font-medium text-gray-700 mb-1">英语成绩</label>
                <div class="relative">
                  <input
                    type="number"
                    id="english"
                    v-model.number="studentForm.english"
                    class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-2 focus:ring-primary/50 focus:border-primary outline-none transition-all"
                    min="0"
                    max="100"
                    :class="{ 'border-danger': formErrors.english }"
                  >
                  <div class="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-400 text-sm">
                    /100
                  </div>
                </div>
                <p v-if="formErrors.english" class="text-danger text-xs mt-1">{{ formErrors.english }}</p>
              </div>
            </div>

            <div class="mt-4 mb-6">
              <label class="block text-sm font-medium text-gray-700 mb-2">成绩状态</label>
              <div class="space-y-2">
                <div>
                  <div class="flex justify-between text-xs mb-1">
                    <span>数学</span>
                    <span class="font-medium">{{ studentForm.math }}</span>
                  </div>
                  <div class="w-full bg-gray-200 rounded-full h-2">
                    <div
                      class="bg-blue-600 h-2 rounded-full score-bar"
                      :style="{ width: (studentForm.math / 100) * 100 + '%' }"
                    ></div>
                  </div>
                </div>
                <div>
                  <div class="flex justify-between text-xs mb-1">
                    <span>英语</span>
                    <span class="font-medium">{{ studentForm.english }}</span>
                  </div>
                  <div class="w-full bg-gray-200 rounded-full h-2">
                    <div
                      class="bg-purple-600 h-2 rounded-full score-bar"
                      :style="{ width: (studentForm.english / 100) * 100 + '%' }"
                    ></div>
                  </div>
                </div>
                <div>
                  <div class="flex justify-between text-xs mb-1">
                    <span>平均分</span>
                    <span class="font-medium">{{ ((studentForm.math + studentForm.english) / 2).toFixed(1) }}</span>
                  </div>
                  <div class="w-full bg-gray-200 rounded-full h-2">
                    <div
                      class="bg-green-600 h-2 rounded-full score-bar"
                      :style="{ width: (((studentForm.math + studentForm.english) / 2) / 100) * 100 + '%' }"
                    ></div>
                  </div>
                </div>
              </div>
            </div>

            <div class="flex justify-end space-x-3">
              <button
                type="button"
                @click="closeStudentModal"
                class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50 transition-colors"
              >
                取消
              </button>
              <button
                type="submit"
                class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors"
              >
                {{ isEditMode ? '保存' : '添加' }}
              </button>
            </div>
          </form>
        </div>
      </div>
    </div>

    <!-- 学生详情模态框 -->
    <div v-if="studentDetailOpen" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 fade-in">
      <div class="bg-white rounded-lg shadow-xl w-full max-w-md mx-4 overflow-hidden transform transition-all slide-in">
        <div class="bg-primary text-white p-4 flex justify-between items-center">
          <h2 class="text-xl font-bold">学生详情</h2>
          <button @click="studentDetailOpen = false" class="text-white hover:text-gray-200">
            <i class="fa fa-times"></i>
          </button>
        </div>
        <div class="p-6">
          <div class="flex items-center justify-center mb-6">
            <div class="w-20 h-20 rounded-full bg-primary/10 flex items-center justify-center">
              <i class="fa fa-user text-primary text-3xl"></i>
            </div>
          </div>

          <div class="space-y-4">
            <div class="flex justify-between items-center">
              <span class="text-gray-600">ID:</span>
              <span class="font-medium">{{ selectedStudent.id }}</span>
            </div>

            <div class="flex justify-between items-center">
              <span class="text-gray-600">姓名:</span>
              <span class="font-medium">{{ selectedStudent.name }}</span>
            </div>

            <div class="flex justify-between items-center">
              <span class="text-gray-600">数学成绩:</span>
              <span
                class="font-medium"
                :class="{
                  'text-success': selectedStudent.math >= 85,
                  'text-warning': selectedStudent.math >= 70 && selectedStudent.math < 85,
                  'text-primary': selectedStudent.math >= 60 && selectedStudent.math < 70,
                  'text-danger': selectedStudent.math < 60
                }"
              >
                {{ selectedStudent.math }}
              </span>
            </div>

            <div class="flex justify-between items-center">
              <span class="text-gray-600">英语成绩:</span>
              <span
                class="font-medium"
                :class="{
                  'text-success': selectedStudent.english >= 85,
                  'text-warning': selectedStudent.english >= 70 && selectedStudent.english < 85,
                  'text-primary': selectedStudent.english >= 60 && selectedStudent.english < 70,
                  'text-danger': selectedStudent.english < 60
                }"
              >
                {{ selectedStudent.english }}
              </span>
            </div>

            <div class="flex justify-between items-center">
              <span class="text-gray-600">平均分:</span>
              <span
                class="font-medium"
                :class="{
                  'text-success': selectedStudent.average >= 85,
                  'text-warning': selectedStudent.average >= 70 && selectedStudent.average < 85,
                  'text-primary': selectedStudent.average >= 60 && selectedStudent.average < 70,
                  'text-danger': selectedStudent.average < 60
                }"
              >
                {{ selectedStudent.average.toFixed(1) }}
              </span>
            </div>

            <div class="pt-4">
              <h4 class="text-sm font-medium text-gray-700 mb-2">成绩状态</h4>
              <div class="grid grid-cols-2 gap-4">
                <div class="bg-blue-50 p-3 rounded-lg">
                  <div class="text-xs text-blue-600 mb-1">数学</div>
                  <div class="flex items-center">
                    <div class="w-full bg-gray-200 rounded-full h-2 mr-2">
                      <div
                        class="bg-blue-600 h-2 rounded-full score-bar"
                        :style="{ width: (selectedStudent.math / 100) * 100 + '%' }"
                      ></div>
                    </div>
                    <span class="text-xs font-medium">{{ selectedStudent.math }}</span>
                  </div>
                </div>

                <div class="bg-purple-50 p-3 rounded-lg">
                  <div class="text-xs text-purple-600 mb-1">英语</div>
                  <div class="flex items-center">
                    <div class="w-full bg-gray-200 rounded-full h-2 mr-2">
                      <div
                        class="bg-purple-600 h-2 rounded-full score-bar"
                        :style="{ width: (selectedStudent.english / 100) * 100 + '%' }"
                      ></div>
                    </div>
                    <span class="text-xs font-medium">{{ selectedStudent.english }}</span>
                  </div>
                </div>
              </div>
            </div>

            <div class="pt-2">
              <h4 class="text-sm font-medium text-gray-700 mb-2">成绩分析</h4>
              <div class="bg-gray-50 p-3 rounded-lg">
                <p class="text-sm text-gray-600">
                  {{ selectedStudent.average >= 85
                    ? '成绩优秀，继续保持！'
                    : selectedStudent.average >= 70
                      ? '成绩良好，有进步空间！'
                      : selectedStudent.average >= 60
                        ? '成绩中等，需要努力提高！'
                        : '成绩不理想，建议加强学习！' }}
                </p>
              </div>
            </div>
          </div>

          <div class="mt-6 flex justify-end space-x-3">
            <button
              @click="studentDetailOpen = false"
              class="px-4 py-2 bg-gray-100 text-gray-700 rounded-md hover:bg-gray-200 transition-colors"
            >
              关闭
            </button>
            <button
              @click="editFromDetail(selectedStudent)"
              class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors"
            >
              编辑信息
            </button>
          </div>
        </div>
      </div>
    </div>

    <!-- 通知组件 -->
    <div v-if="notification.show" class="fixed top-4 right-4 z-50 slide-in" :class="{ 'bg-success': notification.type === 'success', 'bg-danger': notification.type === 'error' }">
      <div class="px-4 py-3 rounded-lg shadow-lg flex items-center">
        <div class="mr-3">
          <i :class="notification.type === 'success' ? 'fa fa-check-circle' : 'fa fa-exclamation-circle'" class="text-white text-xl"></i>
        </div>
        <div class="text-white">
          <h4 class="font-medium">{{ notification.title }}</h4>
          <p class="text-sm opacity-90">{{ notification.message }}</p>
        </div>
        <button @click="hideNotification" class="ml-4 text-white opacity-70 hover:opacity-100">
          <i class="fa fa-times"></i>
        </button>
      </div>
    </div>

    <!-- 页脚 -->
    <footer class="bg-dark text-white py-6 mt-12">
      <div class="container mx-auto px-4">
        <div class="flex flex-col md:flex-row justify-between items-center">
          <div class="mb-4 md:mb-0">
            <p class="text-sm text-gray-400">© 2023 学生成绩管理系统 | 教育科技有限公司</p>
          </div>
          <div class="flex space-x-4">
            <a href="#" class="text-gray-400 hover:text-white transition-colors">
              <i class="fa fa-github text-xl"></i>
            </a>
            <a href="#" class="text-gray-400 hover:text-white transition-colors">
              <i class="fa fa-twitter text-xl"></i>
            </a>
            <a href="#" class="text-gray-400 hover:text-white transition-colors">
              <i class="fa fa-linkedin text-xl"></i>
            </a>
          </div>
        </div>
      </div>
    </footer>
  </div>

  <script>
    const { createApp, ref, computed, reactive, toRefs, watch } = Vue;

    createApp({
      setup() {
        // 数据结构
        const students = ref([
          { id: 1, name: "张三", math: 90, english: 85 },
          { id: 2, name: "李四", math: 78, english: 92 },
          { id: 3, name: "王五", math: 95, english: 88 },
          { id: 4, name: "赵六", math: 65, english: 72 },
          { id: 5, name: "钱七", math: 82, english: 86 },
          { id: 6, name: "孙八", math: 71, english: 79 },
          { id: 7, name: "周九", math: 88, english: 94 },
          { id: 8, name: "吴十", math: 92, english: 81 },
          { id: 9, name: "郑十一", math: 68, english: 75 },
          { id: 10, name: "王十二", math: 85, english: 89 },
          { id: 11, name: "陈十三", math: 76, english: 83 },
          { id: 12, name: "杨十四", math: 91, english: 96 },
          { id: 13, name: "黄十五", math: 79, english: 87 },
          { id: 14, name: "刘十六", math: 84, english: 82 },
          { id: 15, name: "林十七", math: 73, english: 77 },
          { id: 16, name: "张十八", math: 86, english: 90 },
          { id: 17, name: "李十九", math: 69, english: 74 },
          { id: 18, name: "王二十", math: 83, english: 85 },
          { id: 19, name: "赵二十一", math: 77, english: 80 },
          { id: 20, name: "钱二十二", math: 89, english: 93 },
        ]);

        // 计算平均分
        students.value.forEach(student => {
          student.average = (student.math + student.english) / 2;
        });

        // 搜索和排序
        const searchQuery = ref('');
        const sortField = ref('id');
        const sortDirection = ref('asc');
        const filterGrade = ref('');

        // 分页
        const currentPage = ref(1);
        const pageSize = ref(10);

        // 模态框状态
        const studentModalOpen = ref(false);
        const studentDetailOpen = ref(false);
        const selectedStudent = ref({});

        // 表单数据
        const studentForm = reactive({
          id: null,
          name: '',
          math: 0,
          english: 0
        });

        // 表单验证错误
        const formErrors = reactive({
          name: '',
          math: '',
          english: ''
        });

        // 编辑模式标志
        const isEditMode = ref(false);

        // 通知状态
        const notification = reactive({
          show: false,
          type: 'success',
          title: '',
          message: ''
        });

        // 过滤和排序后的学生列表
        const filteredStudents = computed(() => {
          // 应用搜索过滤
          let result = students.value.filter(student =>
            student.name.toLowerCase().includes(searchQuery.value.toLowerCase())
          );

          // 应用成绩过滤
          if (filterGrade.value) {
            result = result.filter(student => {
              if (filterGrade.value === 'excellent') return student.average >= 85;
              if (filterGrade.value === 'good') return student.average >= 70 && student.average < 85;
              if (filterGrade.value === 'average') return student.average >= 60 && student.average < 70;
              if (filterGrade.value === 'poor') return student.average < 60;
              return true;
            });
          }

          // 应用排序
          result.sort((a, b) => {
            if (sortField.value === 'average') {
              return sortDirection.value === 'asc'
                ? a.average - b.average
                : b.average - a.average;
            } else {
              if (typeof a[sortField.value] === 'string') {
                return sortDirection.value === 'asc'
                  ? a[sortField.value].localeCompare(b[sortField.value])
                  : b[sortField.value].localeCompare(a[sortField.value]);
              } else {
                return sortDirection.value === 'asc'
                  ? a[sortField.value] - b[sortField.value]
                  : b[sortField.value] - a[sortField.value];
              }
            }
          });

          return result;
        });

        // 打开添加学生模态框
        const openAddStudentModal = () => {
          // 重置表单
          resetStudentForm();
          isEditMode.value = false;
          studentModalOpen.value = true;
        };

        // 重置学生表单
        const resetStudentForm = () => {
          studentForm.id = null;
          studentForm.name = '';
          studentForm.math = 0;
          studentForm.english = 0;
          Object.keys(formErrors).forEach(key => {
            formErrors[key] = '';
          });
        };

        // 编辑学生
        const editStudent = (student, event) => {
          // 阻止事件冒泡，防止触发行点击事件
          event.stopPropagation();

          // 填充表单
          studentForm.id = student.id;
          studentForm.name = student.name;
          studentForm.math = student.math;
          studentForm.english = student.english;

          isEditMode.value = true;
          studentModalOpen.value = true;
        };

        // 从详情页编辑学生
        const editFromDetail = (student) => {
          studentDetailOpen.value = false;

          // 延迟一点时间，让详情模态框先关闭
          setTimeout(() => {
            // 填充表单
            studentForm.id = student.id;
            studentForm.name = student.name;
            studentForm.math = student.math;
            studentForm.english = student.english;

            isEditMode.value = true;
            studentModalOpen.value = true;
          }, 300);
        };

        // 保存学生
        const saveStudent = () => {
          // 表单验证
          let isValid = true;
          Object.keys(formErrors).forEach(key => {
            formErrors[key] = '';
          });

          if (!studentForm.name.trim()) {
            formErrors.name = '请输入学生姓名';
            isValid = false;
          }

          if (studentForm.math < 0 || studentForm.math > 100 || isNaN(studentForm.math)) {
            formErrors.math = '数学成绩必须在0-100之间';
            isValid = false;
          }

          if (studentForm.english < 0 || studentForm.english > 100 || isNaN(studentForm.english)) {
            formErrors.english = '英语成绩必须在0-100之间';
            isValid = false;
          }

          if (!isValid) return;

          // 创建新学生
          if (!isEditMode.value) {
            // 生成新ID
            const newId = Math.max(...students.value.map(student => student.id), 0) + 1;

            // 添加新学生
            students.value.push({
              id: newId,
              name: studentForm.name,
              math: Number(studentForm.math),
              english: Number(studentForm.english),
              average: (Number(studentForm.math) + Number(studentForm.english)) / 2
            });

            showNotification('success', '添加成功', '学生信息已成功添加');
          }
          // 更新现有学生
          else {
            const index = students.value.findIndex(student => student.id === studentForm.id);
            if (index !== -1) {
              students.value[index] = {
                ...students.value[index],
                name: studentForm.name,
                math: Number(studentForm.math),
                english: Number(studentForm.english),
                average: (Number(studentForm.math) + Number(studentForm.english)) / 2
              };

              showNotification('success', '更新成功', '学生信息已成功更新');
            }
          }

          // 关闭模态框
          closeStudentModal();
        };

        // 关闭学生模态框
        const closeStudentModal = () => {
          studentModalOpen.value = false;
          // 重置表单
          setTimeout(() => {
            resetStudentForm();
          }, 300);
        };

        // 删除学生
        const deleteStudent = (id, event) => {
          // 阻止事件冒泡，防止触发行点击事件
          event.stopPropagation();

          if (confirm('确定要删除该学生吗？此操作不可撤销。')) {
            const studentToDelete = students.value.find(student => student.id === id);
            if (studentToDelete) {
              students.value = students.value.filter(student => student.id !== id);
              showNotification('success', '删除成功', `已删除学生 ${studentToDelete.name}`);
            }
          }
        };

        // 显示学生详情
        const showStudentDetail = (student) => {
          selectedStudent.value = { ...student };
          studentDetailOpen.value = true;
        };

        // 按字段排序
        const sortBy = (field) => {
          if (sortField.value === field) {
            sortDirection.value = sortDirection.value === 'asc' ? 'desc' : 'asc';
          } else {
            sortField.value = field;
            sortDirection.value = 'asc';
          }
        };

        // 上一页
        const prevPage = () => {
          if (currentPage.value > 1) {
            currentPage.value--;
          }
        };

        // 下一页
        const nextPage = () => {
          if (currentPage.value * pageSize.value < filteredStudents.value.length) {
            currentPage.value++;
          }
        };

        // 重置筛选条件
        const resetFilters = () => {
          searchQuery.value = '';
          filterGrade.value = '';
          sortField.value = 'id';
          sortDirection.value = 'asc';
          currentPage.value = 1;
        };

        // 显示通知
        const showNotification = (type, title, message) => {
          notification.type = type;
          notification.title = title;
          notification.message = message;
          notification.show = true;

          // 自动关闭
          setTimeout(() => {
            hideNotification();
          }, 3000);
        };

        // 隐藏通知
        const hideNotification = () => {
          notification.show = false;
        };

        // 监听搜索和筛选变化，重置分页
        watch([searchQuery, filterGrade, sortField, sortDirection], () => {
          currentPage.value = 1;
        });

        return {
          students,
          searchQuery,
          sortField,
          sortDirection,
          filterGrade,
          currentPage,
          pageSize,
          studentModalOpen,
          studentDetailOpen,
          selectedStudent,
          studentForm,
          ...toRefs(formErrors),
          filteredStudents,
          isEditMode,
          notification,
          openAddStudentModal,
          resetStudentForm,
          editStudent,
          editFromDetail,
          saveStudent,
          closeStudentModal,
          deleteStudent,
          showStudentDetail,
          sortBy,
          prevPage,
          nextPage,
          resetFilters,
          showNotification,
          hideNotification
        };
      }
    }).mount('#app');
  </script>
</body>
</html>